package utils

import (
	"archive/zip"
	"crypto/md5"
	"crypto/tls"
	"encoding/hex"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

// GetFileName 获取文件名称，不太扩展名
func GetFileName(fp string) (fName string) {
	filename := filepath.Base(fp)
	// 去除扩展名
	fName = strings.TrimSuffix(filename, filepath.Ext(filename))
	return
}

// GetFileSuffix 获取文件后缀名
func GetFileSuffix(fp string) (suf string) {
	parts := strings.Split(fp, ".")
	if len(parts) > 1 {
		return parts[len(parts)-1]
	}
	return ""
}

// GetFileSize 获取文件大小,不检查文件是否存在，自己判断
func GetFileSize(fp string) (size int64) {
	f, err := os.Stat(fp)
	if err != nil {
		return 0
	}
	return f.Size()
}

// GetFileMD5 获取文件md5,不检查文件是否存在，自己判断
func GetFileMD5(fp string) (str string) {
	file, err := os.Open(fp)
	if err != nil {
		return ""
	}
	defer file.Close()
	hash := md5.New()
	if _, err := io.Copy(hash, file); err != nil {
		return ""
	}
	return hex.EncodeToString(hash.Sum(nil))
}

// CreateFolder 如果目录不存在就创建目录
func CreateFolder(dirName string) (err error) {
	// 检查目录是否存在
	if _, err = os.Stat(dirName); os.IsNotExist(err) {
		// 目录不存在，创建目录
		err = os.Mkdir(dirName, 0755) // 设置权限为0755
		if err != nil {
			return err
		}
		return nil
	} else {
		return nil
	}
}

// ReadToFile WriteToFile 的逆向操作
func ReadToFile(filePath string) (content []byte, err error) {
	f, err := os.OpenFile(filePath, os.O_RDONLY, os.ModeAppend)
	if err != nil {
		return
	}
	return io.ReadAll(f)
}

// ClearFile 清空文件内容
func ClearFile(fp string) (err error) {
	var file *os.File
	file, err = os.OpenFile(fp, os.O_WRONLY|os.O_TRUNC, 0666)
	if err != nil {
		return
	}
	defer file.Close()
	return file.Truncate(0)
}

// IsExistFile 检查文件是否存在,如果是文件夹也返回false.空文件也是false
func IsExistFile(p string) (b bool) {
	fi, err := os.Stat(p)
	if err != nil {
		return false
	}
	if fi.IsDir() {
		return false
	}
	return fi.Size() > 0
}

// IsExistFolder 检查文件夹是否存在
func IsExistFolder(p string) (b bool) {
	fi, err := os.Stat(p)
	if err != nil {
		return false
	}
	return fi.IsDir()
}

// DownloadFile 通过http请求下载文件
func DownloadFile(uri string, savePath string) (err error) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	res, err := client.Get(uri)
	if err != nil {
		return
	}
	defer res.Body.Close()
	f, err := os.Create(savePath)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(f, res.Body)
	return err
}

// Unzip 解压zip文件
func Unzip(zipFile string, destDir string) (err error) {
	zipReader, err := zip.OpenReader(zipFile)
	if err != nil {
		return err
	}
	defer zipReader.Close()
	for _, f := range zipReader.File {
		fpath := filepath.Join(destDir, f.Name)
		if f.FileInfo().IsDir() {
			if err = os.MkdirAll(fpath, os.ModePerm); err != nil {
				return err
			}
		} else {
			if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
				return err
			}
			inFile, err := f.Open()
			if err != nil {
				return err
			}
			outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
			if err != nil {
				return err
			}
			_, err = io.Copy(outFile, inFile)
			if err != nil {
				return err
			}
			if err := inFile.Close(); err != nil {
				return err
			}
			if err := outFile.Close(); err != nil {
				return err
			}
		}
	}
	return nil
}

// AppendWrite 追加写
func AppendWrite(filepath string, content []byte) (err error) {
	// 以追加模式打开文件（如果不存在则创建）
	// os.O_APPEND - 追加模式
	// os.O_CREATE - 如果文件不存在则创建
	// os.O_WRONLY - 只写模式
	file, err := os.OpenFile(filepath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer file.Close()
	// 写入内容
	_, err = file.Write(content)
	return
}

func CopyFile(src, dst string) error {
	// 打开源文件
	sourceFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("无法打开源文件: %v", err)
	}
	defer sourceFile.Close()

	// 创建目标目录（如果不存在）
	dstDir := filepath.Dir(dst)
	if err := os.MkdirAll(dstDir, 0755); err != nil {
		return fmt.Errorf("无法创建目标目录: %v", err)
	}

	// 创建目标文件
	destFile, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("无法创建目标文件: %v", err)
	}
	defer destFile.Close()

	// 复制文件内容
	_, err = io.Copy(destFile, sourceFile)
	if err != nil {
		return fmt.Errorf("复制文件失败: %v", err)
	}

	// 确保所有数据都写入磁盘
	err = destFile.Sync()
	if err != nil {
		return fmt.Errorf("同步文件失败: %v", err)
	}
	return nil
}
